/*
 *所有关于Fk_reim类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*Fk_reimService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using VOL.Core.BaseProvider;
using VOL.Core.Extensions.AutofacManager;
using VOL.Entity.DomainModels;
using System.Linq;
using VOL.Core.Utilities;
using System.Linq.Expressions;
using VOL.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using VOL.MyTable.IRepositories;
using VOL.Core.ManageUser;
using System;
using System.Collections;
using VOL.Core.DBManager;
using System.Collections.Generic;
using VOL.MyTable.Repositories;

namespace VOL.MyTable.Services
{
    public partial class Fk_reimService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IFk_reimRepository _repository;//访问数据库
        WebResponseContent webResponse = new WebResponseContent();
        [ActivatorUtilitiesConstructor]
        public Fk_reimService(
            IFk_reimRepository dbRepository,
            IHttpContextAccessor httpContextAccessor
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }

        public Fk_reimService()
        {
        }
        public override WebResponseContent Export(PageDataOptions pageData)
        {
            return base.Export(pageData);
        }
        public override PageGridData<Fk_reim> GetPageData(PageDataOptions options)
        {

            Hashtable rtn_hst = new Hashtable();

            string loginid = UserContext.Current.GetUserInfo(UserContext.Current.UserId).UserName;


            IQueryable<Ren_oa> queryeable = repository.DbContext.Set<Ren_oa>();

            List<Ren_oa> single = queryeable.Where(w => w.LOGINID == loginid).ToList();
            //queryeable.Where(w => w.LOGINID == "xianshun.huang").Select(t => t.DEPARTMENTID).ToList();
            decimal? depid_oa = 0;
            if (single.Count > 0)
            {
                //depid_oa = single[0].DEPARTMENTID;
                depid_oa = wfoa_tools.get_oayidepidfrom_userid(loginid);
                rtn_hst.Add("depid_oa", depid_oa);
            }
            else
            {
                rtn_hst.Add("depid_oa", -100);//没有部门的直接给部门号-100
            }
            rtn_hst.Add("currdate", DateTime.Now.ToString());
            rtn_hst.Add("username", UserContext.Current.GetUserInfo(UserContext.Current.UserId).UserTrueName);
            rtn_hst.Add("loginid", loginid);//用于判断前端的权限，哪些按钮可用和不可用；

            //查询前可以自已设定查询表达式的条件
            QueryRelativeExpression = (IQueryable<Fk_reim> queryable) =>
            {          
                //优先取需要汇签的人数据
                queryable = queryable.Where(x => x.hq_username.Contains(UserContext.Current.UserName) || ((x.hq_username==null || x.hq_username =="") && x.step_username.Contains(UserContext.Current.UserName)));
                return queryable;

            };

            IQueryable<Fk_yusuan> ys_query = Fk_yusuanRepository.//预算
            Instance.FindAsIQueryable(t =>t.gjahr==DateTime.Now.Year);

            rtn_hst.Add("ys_query", ys_query);//用于前端可用额度计算

            IQueryable<Fk_reimfloat> rf_sqj = Fk_reimfloatRepository.//申请解除可用额度限制
            Instance.FindAsIQueryable(t => t.node_type == "sqj" || t.node_type == "sqj_ok");
            rtn_hst.Add("rf_sqj", rf_sqj);//用于前端申请解除可用额度限制

            /*  IQueryable<Fk_reimfloat> rf = Fk_reimfloatRepository.//查询
             Instance.FindAsIQueryable(t => t.gjahr == DateTime.Now.Year);*/

            var rtn = base.GetPageData(options);

            int[]reim_ids = rtn.rows.Select(t => t.reim_id).ToArray();

            IQueryable<Fk_reimlist> _reimlist = Fk_reimlistRepository.//申请解除可用额度限制
            Instance.FindAsIQueryable(t=>reim_ids.Contains((int)t.reim_id));//类型转换很重要
            rtn_hst.Add("reimlist", _reimlist);//明细表

            
            List<string> tb_list = DBServerProvider.DbContext.Set<Sys_TableColumn>()
               .Where(t =>(t.TableName== "fk_reim") && (t.IsReadDataset==0)).Select(s=>s.ColumnName).ToList();//查询fk_reim表中允许编辑的字段
            rtn_hst.Add("tb_list", tb_list);
            rtn.extra = rtn_hst;//添加额外数据给web客户端，在前端的searchAfter事件中可以查询
            return rtn;
        }

        /// <summary>
        /// 此方法，如果有合计字段必须要有,这种方式对子表进行合计
        /// </summary>
        /// <typeparam name="detail"></typeparam>
        /// <param name="queryeable"></param>
        /// <returns></returns>
        protected override object GetDetailSummary<detail>(IQueryable<detail> queryeable)
        {
            return (queryeable as IQueryable<Fk_reimlist>).GroupBy(x => 1).Select(x => new
            {
                //Weight/Qty注意大小写和数据库字段大小写一样
                je = x.Sum(o => o.je),
                ws_je = x.Sum(o => o.ws_je),
                tax=x.Sum(o => o.tax),
            }).FirstOrDefault();
        }

        public override WebResponseContent Update(SaveModel saveModel)
        {

            //编辑方法保存数据库前处理,
            //注意新增和变更、删除都不是不同的参数****************2022年5月20日 20:39:41 huangxs
            //第二参数是新增数据,第三参数是明细表更改数据
            UpdateOnExecuting = (Fk_reim fk_reim, object addList,object list, List<object> delKeys) =>
            {

                if ((((List<Fk_reimlist>)list).Count == 0) && (((List<Fk_reimlist>)addList).Count == 0))
                {
                    return webResponse.Error("行项目必须要填写！");
                }
                List<(string, string)> tt = ((List<Fk_reimlist>)list).Select(t => (t.fei_type, t.rcntr)).Distinct().ToList();//对更改的数据效验
                if (tt.Count > 1)
                {
                    return webResponse.Error("行项目成本中心与科目必须相同！");
                }
                if (((List<Fk_reimlist>)list).Count > 0)
                {
                    List<Fk_flow> fkflow_list = DBServerProvider.DbContext.Set<Fk_flow>().Where(w => w.racct == tt[0].Item1.ToString() && w.rcntr == tt[0].Item2).ToList();
                    if (fkflow_list.Count == 0)
                    {
                        return webResponse.Error("请通知系统管理员新增此业务流程！");
                    }
                }
               

               

                if (is_not_double_ph((List<Fk_reimlist>)list) == false)//更改部分
                {
                    return webResponse.Error("请检查票号是否重复或者票号为空1");
                }
                if (addList != null)//新增部分
                {
                    if (is_not_double_ph((List<Fk_reimlist>)addList) == false)
                    {
                        return webResponse.Error("请检查票号是否重复2");
                    }
                }
               
                //addList新增明细表
                List<Fk_reimlist> rl = list as List<Fk_reimlist>;//list为明细表
                //list//修改的明细表
                List<Fk_reimlist> addList_rl = addList as List<Fk_reimlist>;//list为明细表
                fk_reim.total_j = rl.Sum(k => (k.je) + addList_rl.Sum(k => (k.je)));
                if (fk_reim.typeid==2) fk_reim.check_je = rl.Sum(k => (k.check_je) + addList_rl.Sum(k => (k.check_je)));//差旅报销时审核金额来自行项目合计

                //Fk_reimfloat表中没有成本中心和科目，只记录流程中的实际情况，所以可以不需要删除
                IQueryable<Fk_reimfloat> _query = Fk_reimfloatRepository.Instance.FindAsIQueryable(t => t.reimid == fk_reim.reim_id);
                List<Fk_reimfloat> ls_dy = _query.Where(w => w.stepid == fk_reim.stepid && w.bek == 0).ToList();
                if (ls_dy.Count > 0)//当前节点为起始节点，初始化Fk_reimfloat表
                {
                        var db = DBServerProvider.DbContext;
                        // IQueryable<Fk_reimfloat> _query = Fk_reimfloatRepository.Instance.FindAsIQueryable(t =>t.reimid==fk_reim.reim_id);
                        DbSet<Fk_reimfloat> Fk_reimfloat_all = DBServerProvider.DbContext.Set<Fk_reimfloat>();
                        Fk_reimfloat_all.RemoveRange(_query);
                        List<Fk_flow> query_f = DBServerProvider.DbContext.Set<Fk_flow>().Where(w => w.racct == tt[0].Item1.ToString() && w.rcntr == tt[0].Item2).ToList();
                        for (int i = 0; i <= query_f.Count - 1; i++)
                        {
                            Fk_reimfloat rf = new Fk_reimfloat();
                            if (query_f[i].bek == 0)//如果是起点流程
                            {
                                rf.bdatetime = DateTime.Now;
                                rf.username = fk_reim.step_username;
                            }

                            rf.stepid = query_f[i].stepid;
                            rf.reimid = fk_reim.reim_id;
                            rf.typeid = fk_reim.typeid;//从前台界面上菜单输入的业务类型，区分费用还是差旅
                            rf.bek = query_f[i].bek;
                            rf.nextroleid = query_f[i].nextroleid;
                            rf.nextstepid = query_f[i].nextstepid;
                            rf.node_attr = query_f[i].node_attr;
                            rf.tj_je=   query_f[i].tj_je;
                            rf.pxm= query_f[i].pxm; 
                            rf.node_type = "key";//表示关键步骤，用于固化流程，不管是回退还是提交都是按key节点
                            rf.roleid = query_f[i].roleid;
                            rf.tjsql = query_f[i].tjsql;
                        IFk_reimfloatRepository fk_reimfloat_repository = Fk_reimfloatRepository.Instance;
                            fk_reimfloat_repository.Add(rf, true);
                        }

                       // db.SaveChanges();//注意不能放在foreach循环里面
                    
                }

                return webResponse.OK("保存成功！！！");
            };
            return base.Update(saveModel);
        }
        /// <summary>
        /// 判断票号是否重复
        /// return true没有重复票
        /// </summary>
        /// <returns></returns>
        private bool is_not_double_ph(List<Fk_reimlist> list)
        {
            //if (list.Count == 0) return false;
            if (list.Select(s=>s.tickno).Distinct().ToArray().Length<list.Count) return false;//防止自己提时重复票
           
            for (int ii = 0; ii <= list.Count-1; ii++)
            {
                if (list[ii].tickno == null) return false;//票号为空
                string[] array_tinckno = Fk_reimlistRepository.Instance.FindAsIQueryable(x => x.tickno == list[ii].tickno &&x.reim_id!=list[0].reim_id).Select(s => s.tickno.Trim()).ToArray();
               // List<Fk_reimlist> rl_list = Fk_reimlistRepository.Instance.FindAsIQueryable(x => array_tinckno.Contains(x.tickno) && x.reim_id != list[ii].reim_id).ToList();
               
               if(array_tinckno.Length >=1) return false;//在保存前,自己的数据还没更新到数据库中
            }
            return true;
        }
        public override WebResponseContent Add(SaveModel saveDataModel)
        {
            
            //新增前确定当前步骤和当前人员
            //list为明细表
            AddOnExecuting = (Fk_reim fk_reim, object list) =>
            {
                if (list==null)
                {
                    return webResponse.Error("行项目必须要填写3");
                }
               if (is_not_double_ph((List < Fk_reimlist >)list) == false)
                {
                    return webResponse.Error("请检查票号是否重复4");   
                }
                List<(string, string)> tt = ((List<Fk_reimlist>)list).Select(t => (t.fei_type, t.rcntr)).Distinct().ToList();

                if (tt.Count > 1)
                {
                    return webResponse.Error("行项目成本中心与科目必须相同！");
                }

                List<Fk_flow> fkflow_list = DBServerProvider.DbContext.Set<Fk_flow>().Where(w => w.racct == tt[0].Item1.ToString() && w.rcntr == tt[0].Item2).ToList();
                if (fkflow_list.Count == 0)
                {
                    return webResponse.Error("请通知管理员新增此业务流程！");
                }

                //fk_reim.total_j = 1234343;
                //IQueryable<Sys_Flow> sf_queryeable = repository.DbContext.Set<Sys_Flow>();
                //根据业务类型获取起始流程步骤号
                //int ?stepid=sf_queryeable.Where(t => (t.typeid == fk_reim.typeid) &&(t.bek==0)).Select(t => t.stepid).FirstOrDefault();//获取流程起始步骤id,bek==0表示流程的起点
                fk_reim.stepid = fkflow_list.Where(t => t.bek == 0).Select(t => t.stepid).FirstOrDefault();//流程起点还是必须的
                fk_reim.step_username = UserContext.Current.GetUserInfo(UserContext.Current.UserId).UserName;

                //计算费用总金额
               if (list != null)
                {
                    List<Fk_reimlist> rl = list as List<Fk_reimlist>;//list为明细表
                    fk_reim.total_j = rl.Sum(k => (k.je));
                    fk_reim.check_je = rl.Sum(k => (k.check_je));


                }

                return webResponse.OK("新增成功！！");
            };

            AddOnExecuted = (Fk_reim fk_reim, object list) =>
            {
                List<(string, string)> tt = ((List<Fk_reimlist>)list).Select(t => (t.fei_type, t.rcntr)).Distinct().ToList();
                List<Fk_flow> query_f = DBServerProvider.DbContext.Set<Fk_flow>().Where(w => w.racct == tt[0].Item1.ToString() && w.rcntr == tt[0].Item2).ToList();

                for (int i=0;i<= query_f.Count-1; i++)
                {
                    Fk_reimfloat rf = new Fk_reimfloat();
                    if (query_f[i].bek == 0)//如果是起点流程
                    {
                        rf.bdatetime = DateTime.Now;
                        rf.username = fk_reim.step_username;
                    }

                    rf.stepid = query_f[i].stepid;      
                    rf.reimid = fk_reim.reim_id;
                    rf.typeid = fk_reim.typeid;//从前台界面上菜单输入的业务类型，区分费用还是差旅
                    rf.bek = query_f[i].bek;
                    rf.nextroleid = query_f[i].nextroleid;
                    rf.nextstepid = query_f[i].nextstepid;
                    rf.node_attr= query_f[i].node_attr;
                    rf.pxm = query_f[i].pxm;
                    rf.node_type = "key";//表示关键步骤，用于固化流程的，不管是回退还是提交都是按key节点
                    rf.roleid = query_f[i].roleid;  
                    rf.tj_je = query_f[i].tj_je;    
                    rf.tjsql = query_f[i].tjsql;   
                    IFk_reimfloatRepository fk_reimfloat_repository = Fk_reimfloatRepository.Instance;
                    fk_reimfloat_repository.Add(rf, true);
                }
                return webResponse.OK("新增成功！！2");
            };

            return base.Add(saveDataModel);
        }
      /*  /// <summary>
        /// 根据部门编码OA，获取该用户的一级部门ID,来自OA用户
        /// </summary>
        /// <param name="currdepartid"></param>
        /// <returns></returns>
        public int? get_oayidepidfrom_depidoa(int currdepartid_oa)
        {
            int? yijdepid = currdepartid_oa;
            while (yijdepid != 0)
            {
                IQueryable<fk_depart> depart_queryeable = fk_departRepository.Instance.FindAsIQueryable(t => (t.depid_oa == yijdepid));
                int? suppdepid = depart_queryeable.Select(t => t.supdepid_oa).FirstOrDefault();
                if (suppdepid == 0)
                {
                    break;//如果上级部门==0,说明本次循环就是一级部门，直接返回yijdepid
                }
                else
                {
                    yijdepid = suppdepid;
                }

            }

            return yijdepid;
        }*/

        /// <summary>
        /// 根据登录用户，获取该用户的一级部门ID,来自OA用户
        /// </summary>
        /// <returns></returns>
        public int? get_oayidepidfrom_userid(string userId)
        {
            return wfoa_tools.get_oayidepidfrom_userid(userId);
        }


    }
}
